package com.rt.schedulenew.web;

import com.rt.schedulebase.dto.DictUsersDto;
import com.rt.schedulebase.dto.ExamApplyDto;
import com.rt.schedulebase.entity.DictUsers;
import com.rt.schedulenew.api.IDictUsersService;
import com.rt.schedulenew.service.impl.ConfigServiceImpl;
import com.rt.schedulenew.utils.base.ConstantsUtil;
import com.rt.schedulenew.utils.base.RequestUtil;
import com.rt.schedulenew.utils.base.ShiroUtil;
import com.rt.schedulenew.utils.checkparam.config.Check;
import com.rt.schedulenew.utils.global.JsonResult;
import com.rt.schedulenew.utils.global.JsonResultUtil;
import com.rt.schedulenew.utils.jwt.common.JwtValidInfo;
import com.rt.schedulenew.utils.jwt.util.JwtTokenUtil;
import com.rt.schedulenew.utils.model.CommonJsonMsg;
import com.rt.schedulenew.utils.util.DateUtil;
import com.rt.schedulenew.utils.util.EhCacheUtil;
import com.rt.schedulenew.utils.util.HttpUtil;
import com.rt.schedulenew.utils.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.*;

@RestController
@RequestMapping({"/"})
public class LoginController {
    private Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private IDictUsersService dictUsersService;
    @Autowired
    private ConfigServiceImpl configService;

    @PostMapping({"/login"})
    @Check({"username", "password"})
    public JsonResult login(@RequestBody DictUsersDto dto, HttpServletRequest req) {
        Subject subject = SecurityUtils.getSubject();
        String userName = dto.getUsername().toUpperCase();
        // 用户名登录失败次数
        Integer failCount = EhCacheUtil.getValue(ConstantsUtil.EhCacheName.loginFail.name(), userName);
        if (Objects.nonNull(failCount) && failCount >= 5) {
            return JsonResultUtil.failure("登录失败次数过多!");
        }
        UsernamePasswordToken userToken = new UsernamePasswordToken(userName, dto.getPassword().toUpperCase());
        try {
            subject.login(userToken);
        } catch (AuthenticationException ae) {
            logger.error("登录失败login:" + ae.getMessage(), ae);
            if (Objects.isNull(failCount)) {
                failCount = 0;
            }
            // 登录失败次数加 1
            EhCacheUtil.put(ConstantsUtil.EhCacheName.loginFail.name(), userName, failCount + 1);
            return JsonResultUtil.failure(ae.getMessage() + "!");
        }
        if (!subject.isAuthenticated()) {
            userToken.clear();
            return JsonResultUtil.failure("登录失败");
        }
        // 清空登录失败次数
        EhCacheUtil.remove(ConstantsUtil.EhCacheName.loginFail.name(), userName);

        JsonResult jsonResult = dictUsersService.getUserLogin(dto.getUsername());
        if (!"0".equals(jsonResult.getStatus())) {
            return jsonResult;
        }
        DictUsersDto dictUsersDto = (DictUsersDto) jsonResult.getResult();
        String sessionId = subject.getSession().getId().toString();
        JwtValidInfo jwtValidInfo = new JwtValidInfo();
        jwtValidInfo.setSessionId(sessionId);
        jwtValidInfo.setUserId(dictUsersDto.getUserId());

        // token过期时间 默认 24小时
        long tokenExpireTime = 24 * 60 * 60 * 1000L;

//        long oneDaySecond = tokenExpireTime;
//        double day = 1.0D;
//        ConfigDto.SystemLoginConfig loginConfig = configService.getSystemLoginConfig();
//        if (Objects.nonNull(loginConfig) && Objects.nonNull(loginConfig.getLoginSet())) {
//            ConfigDto.SystemLoginSet loginSet = loginConfig.getLoginSet();
//            if ("1".equals(loginSet.getValidPeriod()) && StringUtils.isNotEmpty(loginSet.getDay())) {
//                try {
//                    day = Double.parseDouble(loginSet.getDay());
//                } catch (NumberFormatException e) {
//
//                }
//            }
//        }
//        // 计算token过期时间
//        tokenExpireTime = Double.valueOf(oneDaySecond * day).longValue();

        // 24小时
        jwtValidInfo.setExpiryTime(tokenExpireTime);
        String token = JwtTokenUtil.createToken(jwtValidInfo);
        EhCacheUtil.put(ConstantsUtil.EhCacheName.tokenCache.name(), token, token);
        dictUsersDto.setToken(token);
        dictUsersDto.setIpAddress(RequestUtil.getRemoteAddr(req));
        dictUsersDto.setPassword(null);
        ShiroUtil.saveCurrentUser(dictUsersDto);
        return JsonResultUtil.success("登录成功", dictUsersDto);
    }


    @PostMapping({"/loginByToken"})
    public JsonResult loginByToken(@RequestBody DictUsersDto dto, HttpServletRequest req) {
        boolean verifyToken = JwtTokenUtil.verifyToken(req.getHeader("token"));
        if (!verifyToken) {
            return JsonResultUtil.failure("设备认证错误！");
        }
        // 单独验证
        if (StringUtils.isBlank(dto.getUserId())) {
            dto.setUserId("ADMIN");
        }
        DictUsersDto userInfo = dictUsersService.getUserInfo(dto.getUserId());
        if (Objects.isNull(userInfo)) {
            logger.error("获取用户信息失败!");
            return JsonResultUtil.failure("用户名或密码不正确！");
        }
        dto.setUsername(userInfo.getUserId());
        dto.setName(userInfo.getUserId());
        dto.setPassword(userInfo.getPassword());

        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken userToken = new UsernamePasswordToken(dto.getUsername().toUpperCase(), dto.getPassword().toUpperCase());
        try {
            subject.login(userToken);
        } catch (AuthenticationException ae) {
            logger.error("用户登录失败:" + ae.getMessage(), ae);
            return JsonResultUtil.failure("用户名或密码不正确！");
        }
        if (!subject.isAuthenticated()) {
            userToken.clear();
            return JsonResultUtil.failure("登录失败");
        }
        JsonResult jsonResult = dictUsersService.getUserLogin(dto.getUsername());
        if (!"0".equals(jsonResult.getStatus())) {
            return jsonResult;
        }
        DictUsersDto dictUsersDto = (DictUsersDto) jsonResult.getResult();
        String sessionId = subject.getSession().getId().toString();
        JwtValidInfo jwtValidInfo = new JwtValidInfo();
        jwtValidInfo.setSessionId(sessionId);
        jwtValidInfo.setUserId(dictUsersDto.getUserId());
        // 24小时
        jwtValidInfo.setExpiryTime(24 * 60 * 60 * 1000L);
        String token = JwtTokenUtil.createToken(jwtValidInfo);
        EhCacheUtil.put(ConstantsUtil.EhCacheName.tokenCache.name(), token, (Serializable) token);
        dictUsersDto.setToken(token);
        dictUsersDto.setIpAddress(RequestUtil.getRemoteAddr(req));
        dictUsersDto.setPassword(null);
        ShiroUtil.saveCurrentUser(dictUsersDto);
        return JsonResultUtil.success("登录成功", dictUsersDto);
    }

    @GetMapping({"/logout"})
    public JsonResult logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return JsonResultUtil.success("注销成功");
    }

    /***
     * 移动端获取token
     * @param dto
     * @param req
     * @return
     */
    @PostMapping({"/getToken"})
    public JsonResult getToken(@RequestBody ExamApplyDto dto, HttpServletRequest req) {
//        if (!configService.getConfigByName("yy_mobile_appId").equals(dto.getAppId())
//                || !configService.getConfigByName("yy_mobile_license").equals(dto.getLicense())) {
//            return JsonResultUtil.failure("获取token失败,appId或license不正确");
//        }
//        UsernamePasswordToken authenticationToken = new UsernamePasswordToken(dto.getAppId(), dto.getAppId(), false);

        Subject subject = SecurityUtils.getSubject();
        String sessionId = subject.getSession().getId().toString();
        // 登录到shrio
        // subject.login(authenticationToken);

        JwtValidInfo jwtValidInfo = new JwtValidInfo();
        jwtValidInfo.setSessionId(sessionId);
        jwtValidInfo.setUserId(dto.getUserId());

        // 24小时
        jwtValidInfo.setExpiryTime(24 * 60 * 60 * 1000L);

        String token = JwtTokenUtil.createToken(jwtValidInfo);
        EhCacheUtil.put(ConstantsUtil.EhCacheName.tokenCache.name(), token, token);
        DictUsersDto usersDto = new DictUsersDto();
        usersDto.setToken(token);
        usersDto.setUserId(dto.getUserId());
        usersDto.setIpAddress(RequestUtil.getRemoteAddr(req));
        usersDto.setStaffType(dto.getUserId());
        usersDto.setRoleId("patient");
        ShiroUtil.saveCurrentUser(usersDto);

        return JsonResultUtil.success("登录成功", usersDto);
    }

    @PostMapping({"/updateUser"})
    public JsonResult updateUser(@RequestBody DictUsersDto dto) {
        dictUsersService.update(dto);
        return JsonResultUtil.success();
    }

    @PostMapping({"/loginSSO"})
    public JsonResult loginSSO(@RequestBody Map<String, String> map, HttpServletRequest req) {
        List<String> params = new ArrayList<>();
        for (String s : map.keySet()) {
            params.add(s + "=" + map.get(s));
        }
        String param = StringUtils.join(params, "&");
        if (StringUtils.isBlank(param)) {
            logger.info("单点登陆参数为空 ");
            return JsonResultUtil.failure("登陆失败");
        }
        Map<String, String> paraMap = new HashMap<>();
        paraMap.put("clientType", "BS");
        paraMap.put("urlParam", param);
        List<Map<String, String>> maps = new ArrayList<>();
        maps.add(paraMap);
        CommonJsonMsg jsonMsg = new CommonJsonMsg();
        jsonMsg.setTitle("单点登录验证服务");
        jsonMsg.setId(DateUtil.formatCurrentTime("yyyyMMddHHmmssS"));
        jsonMsg.setType("PJ0009");
        jsonMsg.setCreateTime(DateUtil.date2Str(new Date(), DateUtil.FORMAT_DATETIME));
        jsonMsg.setFrom("本消息来自于检查预约");
        CommonJsonMsg.JsonMsgContent content = new CommonJsonMsg.JsonMsgContent();
        content.setResult(maps);
        jsonMsg.setContent(content);
        String bodyContent = JsonUtil.toJson(jsonMsg);
        HttpUtil httpUtil = new HttpUtil();
        String httpUrl = configService.getConfigByName(ConstantsUtil.ConfigName.YY_LOGINSSOURL.getKey());
        logger.info("单点登录,URL :{} ,参数 :{}", httpUrl, bodyContent);
        String result = httpUtil.sendHttpPostBody(httpUrl, bodyContent);
        logger.info("单点登录:" + result);
        if (StringUtils.isBlank(result)) {
            logger.info("内部单点登陆接口返回参数为空");
            return JsonResultUtil.failure("登陆失败");
        }
        CommonJsonMsg jsonResult = JsonUtil.toBean(result, CommonJsonMsg.class);
        CommonJsonMsg.JsonMsgContent resultContent = jsonResult.getContent();
        if (resultContent == null || !resultContent.getStatus().equals("0")) {
            logger.info("内部单点登陆接口接口返回失败");
            return JsonResultUtil.failure("登陆失败");
        }
        maps = resultContent.getResult();
        paraMap = maps.get(0);
        String userId = paraMap.get("userId");
        logger.info("内部单点登陆接口返回参数 userId:" + userId);
        if (StringUtils.isBlank(userId)) {
            return JsonResultUtil.failure("登陆失败");
        }
        DictUsersDto dictUsersDto = new DictUsersDto();
        dictUsersDto.setUserId(userId);
        DictUsers dictUsers = dictUsersService.getInfo(dictUsersDto);
        dictUsersDto.setUsername(userId);
        dictUsersDto.setPassword(dictUsers.getPassword());
        return login(dictUsersDto, req);
    }
}
